﻿Imports System
Imports System.CodeDom
Imports System.Globalization
Imports System.Reflection
Imports System.Text
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class FieldReferenceExpression
        Inherits RuleExpressionInternal
        ' Methods
        Friend Overrides Sub AnalyzeUsage(ByVal expression As CodeExpression, ByVal analysis As RuleAnalysis, ByVal isRead As Boolean, ByVal isWritten As Boolean, ByVal qualifier As RulePathQualifier)
            Dim expression2 As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            Dim targetObject As CodeExpression = expression2.TargetObject
            RuleExpressionWalker.AnalyzeUsage(analysis, targetObject, isRead, isWritten, New RulePathQualifier(expression2.FieldName, qualifier))
        End Sub

        Friend Overrides Function Clone(ByVal expression As CodeExpression) As CodeExpression
            Dim expression2 As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            Return New CodeFieldReferenceExpression { _
                .FieldName = expression2.FieldName, _
                .TargetObject = RuleExpressionWalker.Clone(expression2.TargetObject) _
            }
        End Function

        Friend Overrides Sub Decompile(ByVal expression As CodeExpression, ByVal stringBuilder As StringBuilder, ByVal parentExpression As CodeExpression)
            Dim expression2 As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            Dim targetObject As CodeExpression = expression2.TargetObject
            If (targetObject Is Nothing) Then
                Dim exception As New RuleEvaluationException(String.Format(CultureInfo.CurrentCulture, Messages.NullFieldTarget, New Object() { expression2.FieldName }))
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            RuleExpressionWalker.Decompile(stringBuilder, targetObject, expression2)
            stringBuilder.Append("."c)
            stringBuilder.Append(expression2.FieldName)
        End Sub

        Friend Overrides Function Evaluate(ByVal expression As CodeExpression, ByVal execution As RuleExecution) As RuleExpressionResult
            Dim expression2 As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            Dim targetObject As Object = RuleExpressionWalker.Evaluate(execution, expression2.TargetObject).Value
            Dim info As RuleFieldExpressionInfo = [TryCast](execution.Validation.ExpressionInfo(expression2),RuleFieldExpressionInfo)
            If (info Is Nothing) Then
                Dim exception As New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, New Object(0  - 1) {}))
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            Return New RuleFieldResult(targetObject, info.FieldInfo)
        End Function

        Friend Overrides Function Match(ByVal expression As CodeExpression, ByVal comperand As CodeExpression) As Boolean
            Dim expression2 As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            Dim expression3 As CodeFieldReferenceExpression = DirectCast(comperand, CodeFieldReferenceExpression)
            Return ((expression2.FieldName = expression3.FieldName) AndAlso RuleExpressionWalker.Match(expression2.TargetObject, expression3.TargetObject))
        End Function

        Friend Overrides Function Validate(ByVal expression As CodeExpression, ByVal validation As RuleValidation, ByVal isWritten As Boolean) As RuleExpressionInfo
            Dim newParent As CodeFieldReferenceExpression = DirectCast(expression, CodeFieldReferenceExpression)
            If (newParent.TargetObject Is Nothing) Then
                Dim item As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.NullFieldTarget, New Object() { newParent.FieldName }), &H53D)
                item.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(item)
                Return Nothing
            End If
            If Not validation.PushParentExpression(newParent) Then
                Return Nothing
            End If
            Dim info As RuleExpressionInfo = RuleExpressionWalker.Validate(validation, newParent.TargetObject, False)
            validation.PopParentExpression
            If (info Is Nothing) Then
                Return Nothing
            End If
            Dim expressionType As Type = info.ExpressionType
            If (expressionType Is Nothing) Then
                Return Nothing
            End If
            If (expressionType Is GetType(NullLiteral)) Then
                Dim error2 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.NullFieldTarget, New Object() { newParent.FieldName }), &H546)
                error2.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error2)
                Return Nothing
            End If
            Dim public As BindingFlags = BindingFlags.Public
            If TypeOf newParent.TargetObject Is CodeTypeReferenceExpression Then
                [public] = ([public] Or (BindingFlags.FlattenHierarchy Or BindingFlags.Static))
            Else
                [public] = ([public] Or BindingFlags.Instance)
            End If
            If validation.AllowInternalMembers(expressionType) Then
                [public] = ([public] Or BindingFlags.NonPublic)
            End If
            Dim field As FieldInfo = expressionType.GetField(newParent.FieldName, [public])
            If (field Is Nothing) Then
                Dim error3 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.UnknownField, New Object() { newParent.FieldName, RuleDecompiler.DecompileType(expressionType) }), &H54A)
                error3.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error3)
                Return Nothing
            End If
            If (field.FieldType Is Nothing) Then
                Dim error4 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CouldNotDetermineMemberType, New Object() { newParent.FieldName }), &H194)
                error4.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error4)
                Return Nothing
            End If
            If (isWritten AndAlso field.IsLiteral) Then
                Dim error5 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.FieldSetNotAllowed, New Object() { newParent.FieldName, RuleDecompiler.DecompileType(expressionType) }), &H17A)
                error5.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error5)
                Return Nothing
            End If
            If Not validation.ValidateMemberAccess(newParent.TargetObject, expressionType, field, field.Name, newParent) Then
                Return Nothing
            End If
            Return New RuleFieldExpressionInfo(field)
        End Function

    End Class
End Namespace

